package com.naonao.sns.video;

import android.util.Log;
import android.util.Base64;
import android.os.Build;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.Context;
import android.content.pm.PackageManager;

import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import org.apache.cordova.CallbackContext;
import org.json.JSONException;
import org.json.JSONArray;
import org.json.JSONObject;

import java.util.List;
import java.util.UUID;
import java.util.ArrayList;
import java.io.File;
import java.io.ByteArrayOutputStream;

import com.hai.mediapicker.util.GalleryFinal;
import com.hai.mediapicker.util.SDKUtil;
import com.hai.mediapicker.entity.Photo;

import com.naonao.sns.util.FileMD5Util;
import com.naonao.sns.util.ResultFlag;

public class VideoPlugin extends CordovaPlugin {

    public static final String TAG = "VideoLog-naonao";
    private static final int PERMISSON_REQUESTCODE = 0x58;
    private static final int ALBUM_CODE = 0x10;
    private static final int CAMERA_CODE = 0x19;

    private CallbackContext callbackContext = null;
    private String actionContext = null;
    private JSONArray argsContext = null;
    private Activity activity = null;
    private Context appContext = null;

    private static String[] needPermissions = {
        Manifest.permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.RECORD_AUDIO,
        Manifest.permission.CAMERA
    };

    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callback)
            throws JSONException {

        callbackContext = callback;
        actionContext = action;
        argsContext = args;
        activity = this.cordova.getActivity();
        appContext = this.cordova.getContext();

        try{
            checkPermissions(needPermissions);
            return true;
        }catch(Exception e) {
            returnDataToJs(new JSONObject(), ResultFlag.ERROR_CODE);
        }

        return super.execute(action, args, callback);
    }

    private String renameFileToMD5(String filePath, boolean isCopy, boolean isImage) {
        String newFilePath = filePath;

        try{
            String md5Code = FileMD5Util.getMd5ByPath(filePath);

            if(!isCopy) {
                String parentPath = new File(filePath).getParent();
                newFilePath = parentPath + "/" + md5Code;
                FileMD5Util.renameFile(filePath, newFilePath);
            }else {
                String uuid = UUID.randomUUID().toString().replaceAll("-", "");

                if(isImage) {
                    newFilePath = SDKUtil.IMAGE_PATH + "/" + uuid.substring(0, 5) + "/" + md5Code;
                    FileMD5Util.copyFile(filePath, newFilePath);
                }else {
                    newFilePath = SDKUtil.VIDEO_PATH + "/" + uuid.substring(0, 5) + "/" + md5Code;
                    FileMD5Util.copyFile(filePath, newFilePath);
                }
            }
        }catch(Exception e) {
            Log.e(TAG, e.toString());
        }

        return newFilePath;
    }

	private void getFromCamera(JSONArray args) throws JSONException {
        final JSONObject result = new JSONObject();
        JSONObject param = (JSONObject)args.get(0);
        String fileType = param.getString("fileType");

        GalleryFinal.captureMedia(activity, fileType, 11000, new GalleryFinal.OnCaptureListener() {
            @Override
            public void onSelected(Photo photo) {
                try{
                    photo.setPath(renameFileToMD5(photo.getPath(), false, false));
                    JSONArray photos = new JSONArray();
                    photos.put(photo);

                    if(photo.getDuration() > 0) {
                        result.put("videoPathList", photos);
                        result.put("fileType", 2);
                    }else {
                        result.put("imagePathList", photos);
                        result.put("fileType", 1);
                    }
                    returnDataToJs(result, ResultFlag.SUCCESS_CODE);
                }catch(Exception e) {
                    Log.e(TAG, e.toString());
                }
            }
        });
    }

    private void getFromAlbum(JSONArray args) throws JSONException {
        final JSONObject result = new JSONObject();
        JSONObject param = (JSONObject)args.get(0);
        Integer fileType = Integer.parseInt(param.getString("fileType"));
        Integer maxImages = Integer.parseInt(param.getString("maxImages"));

        GalleryFinal.selectMedias(activity, fileType, maxImages, new GalleryFinal.OnSelectMediaListener() {
            @Override
            public void onSelected(ArrayList<Photo> photoArrayList) {
                try{
                    JSONArray photos = new JSONArray();
                    for(Photo p: photoArrayList) {
                        if(p.getDuration() > 0) {
                            if(p.getPath().contains("naonaoApp/video")) {
                                p.setPath(renameFileToMD5(p.getPath(), false, false));
                            }else {
                                p.setPath(renameFileToMD5(p.getPath(), true, false));
                            }
                        }else {
                            p.setPath(renameFileToMD5(p.getPath(), true, true));
                        }

                        photos.put(p);
                    }
                    if(photoArrayList.get(0).getDuration() > 0) {
                        result.put("videoPathList", photos);
                        result.put("fileType", 2);
                    }else {
                        result.put("imagePathList", photos);
                        result.put("fileType", 1);
                    }
                    returnDataToJs(result, ResultFlag.SUCCESS_CODE);
                }catch(Exception e) {
                    Log.e(TAG, e.toString());
                }
            }
        });
    }

    private void whatToExecute() throws JSONException {
        try{
            if("getFromCamer".equals(actionContext)) {
                getFromCamera(argsContext);
            }else if("getFromPhotoAlbum".equals(actionContext)) {
                getFromAlbum(argsContext);
            }
        }catch(Exception e) {
            returnDataToJs(new JSONObject(), ResultFlag.ERROR_CODE);
        }
    }

    private List<String> findDeniedPermissions(String[] permissions) {
        List<String> needRequestPermissonList = new ArrayList<>();
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            for(String perm: permissions) {
                if(appContext.checkSelfPermission(perm) != PackageManager.PERMISSION_GRANTED) {
                    needRequestPermissonList.add(perm);
                }
            }
        }
        return needRequestPermissonList;
    }

    private void checkPermissions(String[] permissions) throws JSONException {
        List<String> needRequestPermissonList = findDeniedPermissions(permissions);
        if(null != needRequestPermissonList && needRequestPermissonList.size() > 0) {
            String[] array = needRequestPermissonList.toArray(new String[needRequestPermissonList.size()]);
            this.cordova.requestPermissions(this, PERMISSON_REQUESTCODE, array);
        }else{
            whatToExecute();
        }
    }

    @Override
    public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults)
            throws JSONException {

        if(requestCode == PERMISSON_REQUESTCODE) {
            if(!verifyPermissions(grantResults)) {
                Log.e(TAG, "获取权限失败");
                returnDataToJs(new JSONObject(), ResultFlag.FAIL_CODE);
            }else {
                whatToExecute();
            }
        }
    }

    private boolean verifyPermissions(int[] grantResults) {
        for(int result: grantResults) {
            if(result != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }

    private void returnDataToJs(JSONObject obj, int code) throws JSONException {
        if(code == ResultFlag.SUCCESS_CODE) {
            obj.put("status", ResultFlag.SUCCESS_STATUS);
        }else if(code == ResultFlag.FAIL_CODE) {
            obj.put("status", ResultFlag.FAIL_STATUS);
        }else if(code == ResultFlag.ERROR_CODE) {
            obj.put("status", ResultFlag.ERROR_STATUS);
        }

        obj.put("code", code);
        PluginResult res = new PluginResult(PluginResult.Status.OK, obj);
        res.setKeepCallback(true);
        callbackContext.sendPluginResult(res);
    }
}
